package com.gzsxy.esjy.response;

import com.alibaba.fastjson.JSON;
import com.gzsxy.esjy.common.SvException;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.handler.codec.http.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;

/**
 * 自定义response
 * @author zhangxiaolong
 * @date 2022/7/6 9:36
 */
public class NettyHttpResponse extends DefaultFullHttpResponse {

	private static final Logger log = LoggerFactory.getLogger(NettyHttpResponse.class);
	
    private static final PooledByteBufAllocator BYTE_BUF_ALLOCATOR = new PooledByteBufAllocator(false);

    private NettyHttpResponse(HttpResponseStatus status, ByteBuf buffer ) {
        super(HttpVersion.HTTP_1_1, status,buffer);
    }
    
    private void setDefaultHeaders(String charset){
    	 headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json;charset="+charset);
         headers().set(HttpHeaderNames.CONTENT_LENGTH,content().readableBytes());
         headers().set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
         headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
         headers().set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_HEADERS, "Origin, X-Requested-With, Content-Type, Accept, RCS-ACCESS-TOKEN");
         headers().set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_METHODS, "GET,POST,PUT,DELETE");
    }

    public static FullHttpResponse createError(Throwable exception,String charset) {
        String message = exception.getClass().getName() + ":" + exception.getMessage();
        return NettyHttpResponse.create(HttpResponseStatus.INTERNAL_SERVER_ERROR, String.format(RESPONSE_FORMAT,HttpResponseStatus.INTERNAL_SERVER_ERROR.reasonPhrase(),message),charset);
    }

    public static FullHttpResponse ok(String content,String charset) {
        return create(HttpResponseStatus.OK,content,charset);
    }

    public static FullHttpResponse create(HttpResponseStatus status,Object content,String charset) {
        byte[] body = JSON.toJSONBytes(content);
        ByteBuf buffer = BYTE_BUF_ALLOCATOR.buffer(body.length);
        buffer.writeBytes(body);
        NettyHttpResponse response = new NettyHttpResponse(status,buffer);
        response.setDefaultHeaders(charset);
        return response;
    }
//    {"timestamp":"2020-06-06 12:22:23","status":500,"error":"Internal Server Error","message":"/ by zero","path":"/appoint/tt"}
    private final static String RESPONSE_FORMAT = "{\"status\":%s,\"message\":\"%s\"}" ;
    
    /**
	 * 处理异常
	 * 
	 * @param e
	 * @param charset
	 * @return
	 */
	public static FullHttpResponse doExceptionResponse(Throwable e, String charset) {
		if (e instanceof SvException) {
			SvException newE = (SvException) e;
			int status = newE.getExceptionCode();
			log.error(e.getMessage(), newE.getRealException() == null ? e : newE.getRealException());
			return NettyHttpResponse.create(HttpResponseStatus.valueOf(status), String.format(RESPONSE_FORMAT, HttpResponseStatus.valueOf(status).toString(),e.getMessage()), charset);
		}
		//拿到反射异常，得到最终异常
		if(e instanceof InvocationTargetException) {
			InvocationTargetException newE = (InvocationTargetException)e ;
			Throwable targetException = newE.getTargetException();
			return doExceptionResponse(targetException, charset) ;
		}
		log.error(e.getMessage(), e);
		return NettyHttpResponse.createError(e, charset);
	}

}

